#ifndef  DATAFILE_HPP
# define DATAFILE_HPP

# include <list>
# include <string>
# include <sstream>

  class DataBranch;
  class DataFile
  {
  public:
    class Factory
    {
    public:
      static DataFile* Yaml(const std::string& filepath);
    };
    
    typedef std::list<DataBranch*> Branches;
    virtual ~DataFile();

    void                     Push(DataBranch*);
    DataBranch&              Protect(const std::string&);
    DataBranch*              operator[](const std::string&);
    virtual void             Output(void) const;
    Branches::const_iterator begin(void) const { return (_branches.begin()); }
    Branches::const_iterator end(void) const   { return (_branches.end()); }
    Branches::iterator       begin(void)       { return (_branches.begin()); }
    Branches::iterator       end(void)         { return (_branches.end()); }
    
    bool                     AssertKeys(const char**, bool useThrow = false);

  protected:
    Branches                _branches;
  };
 
  class DataBranch : public DataFile
  {
  public:
    DataBranch(const std::string&, DataBranch* = 0);

    bool                   operator==(const std::string&) const;
    void                   operator=(const std::string& v) { _value = v; }
    const std::string&     Key(void) const                 { return (_key); }
    const std::string&     Value(void) const               { return (_value); }
    DataBranch*            Father(void)                    { return (_father); }
    void                   Output(void) const;

    template<typename T>
    operator T() const
    {
      std::stringstream    stream;
      T                    output;

      stream << _value;
      stream >> output;
      return (output);
    }

    template<typename T>
    T                        operator()(const std::string& key, const T& def)
    {
      DataBranch*            data = operator[](key);

      if (!(data))
        return (def);
      return (data);
    }

  private:
    DataBranch*            _father;
    const std::string      _key;
    std::string            _value;
  };
#endif 
